<!-- 高德地图 -->
<template>
  <PageWrapper title="高德地图" content="演示常用示例">
    <div class="demo-amap-app-container">
      <MySearchSelect
        placeholder="搜索地点"
        class="maps-search-select"
        @select="handleSelect"
        :api="handleFetch"
        v-model:value="searchValue"
        resultField="data"
        :customOptions="true"
        :style="{ width: '450px' }"
        show-search
        allowClear
      >
        <template #customOptions="options">
          <template v-for="item in options" :key="`${item.value}`">
            <SelectOption :value="item.value">
              <div class="addree-option">
                <span class="label">{{ item.label }}</span>
                <span class="detail">{{ item.detail }}</span>
              </div>
            </SelectOption>
          </template>
        </template>
      </MySearchSelect>

      <div style="background-color: #ffffff">
        <div id="demo-amap-container"></div>
      </div>
    </div>
    <InfoWindow :selectAddress="selectAddress" @confirm="handleConfirmSelectAddress" ref="infoWindowRef" />
  </PageWrapper>
</template>

<script lang="ts" setup>
  import { PageWrapper } from "/@/components/Page"
  import MySearchSelect from "/@/components/Form/src/my/components/MySearchSelect.vue"
  import { SelectOption } from "ant-design-vue"
  import AMapLoader from "@amap/amap-jsapi-loader"
  import InfoWindow from "./InfoWindow.vue"
  import { useMessage } from "/@/hooks/web/useMessage"
  /*在Vue3中使用时,需要引入Vue3中的shallowRef方法(使用shallowRef进行非深度监听,
因为在Vue3中所使用的Proxy拦截操作会改变JSAPI原生对象,所以此处需要区别Vue2使用方式对地图对象进行非深度监听,
否则会出现问题,建议JSAPI相关对象采用非响应式的普通对象来存储)*/
  // import { shallowRef } from '@vue/reactivity';
  import { ref, onMounted, onUnmounted } from "vue"

  const { createMessage, createErrorModal } = useMessage()
  // const map = shallowRef(null);
  let map = null
  let MyAMap: any = null
  const infoWindowRef = ref()
  const searchValue = ref("")
  const selectAddress = ref<any>({})
  const mapPlugin: any = {}

  interface Location {
    lat?: string
    lng?: string
  }
  interface Pois {
    // Location
    location: string[]
    pname: string
    cityname: string
    adname: string
    address: string
    name: string
    id: string
  }
  interface PoiList {
    pois: Pois[]
    count: number
    pageIndex: number
    pageSize: number
  }

  interface PoiResult {
    poiList: PoiList
  }

  // @ts-ignore
  let poiResult: PoiResult = []

  let autoCompleteResult: any = []
  let autoOptions = {}

  onUnmounted(() => {
    // @ts-ignore
    map && map.destroy()
    console.log("地图已被销毁")
  })

  const initMap = () => {
    // @ts-ignore
    window._AMapSecurityConfig = {
      securityJsCode: "1974107b6292da50002dfb008168e5cc",
    }
    AMapLoader.load({
      // 申请好的Web端开发者Key，首次调用 load 时必填
      key: "66526c96e5fad2b84005d594162a455e",
      // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
      version: "2.0",
      // plugins:[''], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
    })
      .then((AMap) => {
        MyAMap = AMap
        map = new AMap.Map("demo-amap-container", {
          //设置地图容器id
          resizeEnable: true,
          viewMode: "2D", //是否为3D地图模式
          zoom: 14, // 初始化地图级别
        })
        //使用CSS默认样式定义地图上的鼠标样式
        map.setDefaultCursor("pointer")

        // 添加插件
        AMap.plugin(
          [
            "AMap.ToolBar",
            "AMap.Scale",
            "AMap.HawkEye",
            "AMap.Geolocation",
            "AMap.MouseTool",
            "AMap.AutoComplete",
            "AMap.PlaceSearch",
            "AMap.Marker",
            "AMap.Pixel",
            "AMap.Geocoder",
          ],
          function () {
            // 异步同时加载多个插件
            // 添加地图插件
            // @ts-ignore
            map.addControl(new AMap.ToolBar()) // 工具条控件;范围选择控件
            // @ts-ignore
            map.addControl(new AMap.Scale()) // 显示当前地图中心的比例尺
            // @ts-ignore
            map.addControl(new AMap.HawkEye()) // 显示缩略图
            // @ts-ignore
            map.addControl(new AMap.Geolocation()) // 定位当前位置

            // 以下是鼠标工具插件
            // const mouseTool = new AMap.MouseTool(map);
            // // mouseTool.rule();// 用户手动绘制折线图,测量距离
            // mouseTool.measureArea(); // 测量面积
          }
        )
        // 单击
        // @ts-ignore
        map.on("click", (e) => {
          // lng ==> 经度值  lat => 维度值
          // @ts-ignore

          const currentLocation = {
            lng: e.lnglat.getLng(),
            lat: e.lnglat.getLat(),
          }
          selectAddress.value.address = ""
          updateMarker(currentLocation)
          handlerOpenInfoWindow(currentLocation)
        })
      })
      .catch((e) => {
        console.log(e)
      })
  }

  onMounted(() => {
    initMap()
  })

  const handleConfirmSelectAddress = (address) => {}

  const handleSelect = async (value) => {
    console.log("handleSelect: ", value)

    // 平移地图
    const poi = autoCompleteResult?.filter((e) => e.id === value)
    if (poi && poi.length > 0) {
      const location = poi[0].location
      selectAddress.value = poi[0]
      ;(selectAddress.value.address = poi[0].district + poi[0].address + poi[0].name), console.log("location", location)

      updateMarker(location)
      handlerOpenInfoWindow(location)
    }
  }

  const handleFetch = (params) => {
    console.log("params", params)
    if (!mapPlugin.placeSearch) {
      // POI搜索插件
      mapPlugin.placeSearch = new MyAMap.PlaceSearch({
        pageSize: 20, // 单页显示结果条数
        pageIndex: 1, // 页码
        citylimit: false, //是否强制限制在设置的城市内搜索
        map: map, // 展现结果的地图实例
        autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
      })
    }

    if (!mapPlugin.autoComplete) {
      mapPlugin.autoComplete = new MyAMap.AutoComplete(autoOptions)
    }

    return new Promise((resolve, reject) => {
      mapPlugin.autoComplete.search(searchValue.value, function (status, result) {
        // 搜索成功时，result即是对应的匹配数据
        console.log("autoComplete", result)
        autoCompleteResult = result.tips || []
        const options = result?.tips
          ?.filter((e) => e.location)
          .map((e) => ({
            label: e.name,
            detail: e.district + e.address + e.name,
            value: e.id,
            key: e.id,
          }))
        resolve(options)
      })
      // //关键字查询
      // mapPlugin.placeSearch.search(searchValue.value, function (status, result) {
      //   // 搜索成功时，result即是对应的匹配数据
      //   poiResult = result
      //   poiResult = JSON.parse(JSON.stringify(result))
      //   console.log(result);
      //   const options = result?.poiList?.pois?.map(e => ({
      //     label: e.name,
      //     detail: e.pname + e.cityname + e.adname,
      //     value: e.id,
      //     key: e.id,
      //   }))
      //   resolve(options)
      // });
    })
  }

  // 实例化点标记

  const updateMarker = (location: Location) => {
    infoWindowRef.value && infoWindowRef.value.hidden()

    // map.clearMap()
    console.log("updateMarker-request: ", location)

    if (!mapPlugin.marker) {
      mapPlugin.marker = new MyAMap.Marker({
        icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
        // position: current_position.value, // 这里我们通过上面的点击获取经纬度坐标,实时添加标记
        // 通过设置 offset 来添加偏移量
        offset: new MyAMap.Pixel(-20, -50),
      })
      mapPlugin.marker.setMap(map)
    }

    // 自定义点标记内容
    let markerContent = document.createElement("div")

    // 点标记中的图标
    let markerImg = document.createElement("img")
    markerImg.className = "markerlnglat"
    markerImg.src = "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png"
    markerContent.appendChild(markerImg)

    // 点标记中的文本
    let markerSpan = document.createElement("span")
    // markerSpan.className = 'map-marker';
    // markerSpan.innerHTML = "所选位置";
    markerContent.appendChild(markerSpan)

    mapPlugin.marker.setContent(markerContent) //更新点标记内容
    mapPlugin.marker.setPosition([location.lng, location.lat]) //更新点标记位置

    mapPlugin.marker.setTop(true)
    // 移动到中心
    map.setCenter(mapPlugin.marker.getPosition())
  }

  const handlerOpenInfoWindow = async (location: Location) => {
    console.log("infoWindow", location)
    if (selectAddress.value.address === "") {
      const addressInfo = await getAddress(location)
      console.log("address", addressInfo)
      selectAddress.value = { ...selectAddress.value, ...addressInfo }
    }

    let infoWindow = new MyAMap.InfoWindow({
      isCustom: true, //使用自定义窗体
      autoMove: true, // 是否自动调整窗体到视野内
      position: [location.lng, location.lat], // 基点位置
      content: document.getElementById("info-window"),
      offset: new MyAMap.Pixel(60, -200),
    })
    infoWindow.open(map, [location.lng, location.lat])
    // 必须也设置一下, 否则居中有问题
    map.setCenter(mapPlugin.marker.getPosition())
    infoWindowRef.value && infoWindowRef.value.show()
  }

  const getAddress = async (location: Location) => {
    if (!mapPlugin.geocoder) {
      mapPlugin.geocoder = new MyAMap.Geocoder({
        city: "010", //城市设为北京，默认：“全国”
        radius: 1000, //范围，默认：500
      })
    }

    // @ts-ignore
    return new Promise((resolve, reject) => {
      // @ts-ignore
      mapPlugin.geocoder.getAddress([location.lng, location.lat], (status, result) => {
        console.log("result", result)
        if (result.regeocode.formattedAddress) {
          const addressComponent = result.regeocode.addressComponent
          resolve({
            address: result.regeocode.formattedAddress,
            name: addressComponent.district + addressComponent.street + addressComponent.township,
            location,
          })
        } else {
          console.error("地址获取失败")

          resolve({})
        }
      })
    })
  }
</script>

<style lang="less">
  #demo-amap-container {
    padding: 0px;
    margin: 0px;
    width: 100%;
    height: 500px;
  }
  .demo-amap-app-container {
    position: relative;
    height: calc(100% - 300px);
  }

  .addree-option {
    display: flex;
    justify-content: space-between;
    .label {
      margin-right: 20px;
    }

    .detail {
      color: #b2b2b2;
    }
  }

  .map-marker {
    position: absolute;
    top: -20px;
    right: -60px;
    color: #fff;
    padding: 4px 10px;
    box-shadow: 1px 1px 1px rgba(10, 10, 10, 0.2);
    white-space: nowrap;
    font-size: 12px;
    font-family: "";
    background-color: #25a5f7;
    border-radius: 3px;
  }

  .maps-search-select {
    position: absolute;
    left: 50%;
    top: 10px;
    border: 1px solid #ccc;
    z-index: 1000;
    transform: translate(-50%-0%);
  }
</style>
